﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using Renci.SshNet.Security;
using Renci.SshNet.Tests.Common;

namespace Renci.SshNet.Tests.Classes.Security.Cryptography
{
    [TestClass]
    public class RsaKeyTest : TestBase
    {
        private static RsaKey GetRsaKey(string fileName, string passPhrase = null)
        {
            using (var stream = GetData(fileName))
            {
                return (RsaKey)new PrivateKeyFile(stream, passPhrase).Key;
            }
        }

        // This is just to line up any differences in the assertion message.
        private static void AssertEqual(byte[] actualBytes, string expectedHex)
        {
            string actualHex = Convert.ToHexString(actualBytes);

            Assert.AreEqual(expectedHex, actualHex,
                $"{Environment.NewLine}Expected: {expectedHex}{Environment.NewLine}  Actual: {actualHex}");
        }

        // These tests generated by converting the keys to PKCS8, importing them to BCL RSA,
        // and printing out the expected RSAParameter values.

        // e.g. sudo ssh-keygen -f Key.OPENSSH.RSA.Encrypted.txt -m PKCS8 -p
        //  or  sudo openssl pkcs8 -topk8 -nocrypt -in Key.RSA.Encrypted.Aes.128.CBC.12345.txt -out Key.RSA.Encrypted.Aes.128.CBC.12345.PKCS8.txt

        /* Something like this:

        using IndentedTextWriter tw = new(Console.Out);

        foreach (string filePath in Directory.EnumerateFiles(dir, "*.RSA.*txt"))
        {
            string pkFile = Path.GetFileNameWithoutExtension(filePath);

            if (pkFile.Contains("Des.CBC"))
            {
                continue;
            }

            tw.WriteLine("[TestMethod]");
            tw.WriteLine($"public void {pkFile.Replace('.', '_')}()");
            tw.WriteLine("{");
            tw.Indent++;

            tw.WriteLine($"RsaKey rsaKey = GetRsaKey(\"{pkFile}.txt\");");
            tw.WriteLine();
            tw.WriteLine("RSAParameters p = rsaKey.GetRSAParameters();");
            tw.WriteLine();

            using RSA rsa = RSA.Create();

            rsa.ImportFromPem(File.ReadAllText(filePath));
            rsa.Dump();
            RSAParameters p = rsa.ExportParameters(true);

            WriteParamAssert(p.Modulus);
            WriteParamAssert(p.Exponent);
            WriteParamAssert(p.D);
            WriteParamAssert(p.P);
            WriteParamAssert(p.Q);
            WriteParamAssert(p.DP);
            WriteParamAssert(p.DQ);
            WriteParamAssert(p.InverseQ);

            tw.Indent--;
            tw.WriteLine("}");
            tw.WriteLine();
        }

        void WriteParamAssert(byte[] bytes, [CallerArgumentExpression(nameof(bytes))] string name = null)
        {
            tw.WriteLine($"AssertEqual({name}, \"{Convert.ToHexString(bytes)}\");");
        }
         */

        [TestMethod]
        public void Key_OPENSSH_RSA_Encrypted()
        {
            RsaKey rsaKey = GetRsaKey("Key.OPENSSH.RSA.Encrypted.txt", "12345");

            RSAParameters p = rsaKey.GetRSAParameters();

            AssertEqual(p.Modulus, "B139F9E6C42D609A65F5F0B0811BF5FBDC1A025D0101100273DD5F70D0531381405E6CADDF91F38C2CDCD69F968C47AD3CC101CE10F6211DF7C225F74947A95458B1D9CF9F846517CCF681E9CAC32D4E8610A06B5BF7133B0F927796759981279AD91EF149EAA90A53799D050C1AEF32D9DD92DE0F68D6FAD375EBBBD6ED3D4053B1D805C13D49828E90AE06537260411031F44CB50E8F0DB3DDBCB335BB295B42A07EFFA8CCB02C8416F94B8ADF46719EC8B4A40DFA3B193663FE7FBCAD5572EC6538CF2DDE66596ADFE93D53D57B7D0C1A0B5E732B9838827FF1178936289C83BA074147BCD502AC3CD9EEBC4879BA9E3CB7ACD50DB2A14AA60BC83E730C37");
            AssertEqual(p.Exponent, "010001");
            AssertEqual(p.D, "2DEF12E046D464076089DFFA3F5C59E30F670659C89AD7E56AD663983FC66875C59333A3D52064F95DDF571941D1D5FA069717BAAB16BFFA9E6E899C9037ACA199E36ECAAB538B4821ED7A3A783D220F0A1C6117B25C5575A75195014035AB0DF2CA77849E5DDDB6397079CC07192C0A0801AFC132493FFEFEB3BF878DEB2B46848044B6344EC3C625D63E9BBCFC87589DB55C6339C5184EB95F8BB917EA061FFB3B5D6ADE5DFFFD309226F7E20C67C0520093B7D4ECF19881E2C86F0CCEDBBDA3DFA2B04EF29240A28F73BC1B1F73E19C52FA2F912ABDCE96677922A48B9F54B0A99C35E6C3A767F709049067C98FA319298A890DC001ABD1359D1498759C21");
            AssertEqual(p.P, "D62A26655E3462A229CE484CFB50A54E3746C6ADC3B816090AC27DA11CD5CABCB30E182869642BB003DEA280FD3039AE17133DEE29C7FEBE3D7FCEA0743DFABC84850758405F7246F68FE636DF88478F282F1BD3F9872A36F771D897FD8E1015AA6DFE6E6B36ADE3D645C5F41B0A3973A8D165A5A09667928D67B933F4DC944F");
            AssertEqual(p.Q, "D3D8A364635253E35A79910243D783B5DA6D173F0EA1A59A057579F59E3ABB84B551F2847ACE555B107DEA2FF7B0C5601FBBE365E9E95FA15CDABF620D6ADAD734E2B77A9497AEAA7B102A65DF58196B0233B8DAB1AC2961B980F208E122FD0FEFD6CC180DC895917601C127FD2D9F0149913E845A28826E943A6651C51BC799");
            AssertEqual(p.DP, "697189440174D3573A34193EE5C19812017F3454DB77284A3D64F2CBBF51B7A6DE95C2E92AB2AA1BD85BE63091F80B7E1E5857F689D5B123E34DA8E331384EDA4078EADBD59DE8BAEDAC7DD1688F45844369A64EE09D5EF87F2E2B50F202DF027BCDFA264D5D379264AE27BF7F0CB2AAB2649EA24485A8EAEBFA34A2531DC35B");
            AssertEqual(p.DQ, "31BE9417758F166DB3880A39EAEE475A43710C5D5D352DEAADCF7914E8D3C7C690C12E5E576BEDF515394BED798F03B9DF99C1FAE3634E765894710E38325832E2933E1C459A1C84A1A3192194C15E2E9774C7BA6AB00F838808B44CCB78E8CD7E3704F3BD00D5C6335C941BACC2B2AC9DB6C26457BB5D6D53D726C19AB43C39");
            AssertEqual(p.InverseQ, "78C7259CE4638FBE9EC3E5389B0118C3865597F6A1B5C8A338337F9FFE9FB838D789311EAB26E700493A473D1FBCE8DA59C2A7D3CA7BD4A127D8D85165651BF4D8E57AADE29140A7DEB47C953792391DAF3DB006AAD2AC00DCDB9D091A6376BE32CFE5E8D2EBE3A37DF2B7B9ED3086ACE3A7BAACBC11E717A1E1A15608F0D2C0");
        }

        [TestMethod]
        public void Key_OPENSSH_RSA()
        {
            RsaKey rsaKey = GetRsaKey("Key.OPENSSH.RSA.txt");

            RSAParameters p = rsaKey.GetRSAParameters();

            AssertEqual(p.Modulus, "ED6ECE8A08BB1E3D66B1ADA5F078A62CFCDA815984FC2B1E30A091C4F313B564EFA1974CB7B85F92D85603B876D1AEE8492787DADEC5A9E3A954D18562F455DC1556B0A64931171D2624C26408C7DFCAD893DD17BD9DE62AB28DFF77DC42C8783A23E75AA4FA1D2AA0D78A2257C50FB54C2713AE6C9164B1BF1B7E10B955A42A86E6F1363BF18D0CA404EC5CD8B7ABD08A1305480041AA3BDABB49A35F4D3629888232BEAF825F176240C0E27E7E272412431CE79DFACBF776686AABA344FD9B4F95215E06F3AFC1C5C2EA901AF5111026534C8F018AFFFAB4E227F71DA111A37ABF10CBB5773DF44D9DE8D5BA71DAE2C1A1852788E05560C4E66534D3A5DD3D");
            AssertEqual(p.Exponent, "010001");
            AssertEqual(p.D, "E9782AFA0A69CCEB7D9EBB6CCF90237F5B479527AC9FB5DA62E0915603DBDE63994AE116DC151D4DAD12AF67E4D67CD206952B7EA9CDDE27722B68376C3D6C6C1443814291F8068D7023774E9C5FC60C957898502EF12411DA2FCD04547F0AD745FC661378E44467D56EFC7296B1BCA77E717265F275E978EABDA2F1D8FC808637B4AA7444CBD9E1994D6E15873DDE4EC721D62FD7B781B392C88CA34204CA65ECE1CC4AD2FD7FCA27F5D8AB3C8102A36A676460D642A21D19474BA284236B7217061F87E45BE8BF71721D52A8EB508535A2AE6C52DB9769183DA381A9577B28B0F0F9AEA938960AA52650CC7A31D177B45B22AEBE782B8400F64A8C79A44BB5");
            AssertEqual(p.P, "FE74F0EA7AC163C0C27D497C166EA90B6371F9C978DE0D9184017726E7D2F56EE54772A9240B6BC86503344E840FAA26FAE5B1980CF61F02C8B4F2BA29BC9629191E87303B5DF3053755690F1CDA526F7F6B974C85CD647B1E4BB21391F0623B5852078CFC44390EAF7E6619F75BC892050301591785ECF169D017EBC711A76B");
            AssertEqual(p.Q, "EEDF6F5E0B05457FD834CCD1DF66EDF5A745AD12B72C46FE7B7EAF94A0FB68BFC9F1505EF5A0E59EE4A4869C6B4C202237D6406D3E151BBDF3A6BAA36B8090638236CF4268B4C52004E4BDD0B8429136395A137FD669D281C338490ED6AEB9893589F92B740569EBB5F2439A6ECAE1A055A40134F6EBC40F60D486F278BE3FF7");
            AssertEqual(p.DP, "3E959697A55FA1604CB5B1F842302F85AC8CE0E9EBBF79C8DB95DCAF85FF3DFC6B8A1A2A7DC20D5D7972C34FB86D7DE51E7A962696B186491202675CE05D10F5C4C6DC6B417EC701F66D1C6CEA24CC77BDF8417B41C195C02E6061C92C70DA484C5DC89BA5844620558B9A2332D2B14F30CA5F6F8138A061742C0966254D3347");
            AssertEqual(p.DQ, "2DB030C5E507BA164CCD348BC3D615179249E2639D036C04CAAC1D7B291B4D1AB9CE5D17FC952CB62A774983EB85E0F38A88814423C6B7CAAA2AAEB20922CAFB2D71BC4CB0683AF7F7D7A472A27BA0F8A51994773414837DEC4FFCB148E09C7E20EE65E928C4CC5098396132CD9422799F47C22F56371C05F0F855635532D65B");
            AssertEqual(p.InverseQ, "B14413D1486AEE5D2E81377863DF3D6C7E9E5B47E8976D7F9BB079CE42507A935A7543D3B35F3CBAFBF88A75BC9F63B74426A75D61D97C227502C47F304116D82E900EDBEA2971DBCDF590942612571075EC28D444A6BC7CD688024F7CCE098D3703B9DCD0657B2AD484F82F9B7C6DEC00A0A735D8E51C0D24BF3F6B458E9A0C");
        }

        [TestMethod]
        public void Key_RSA_Encrypted_Aes_128_CBC_12345()
        {
            RsaKey rsaKey = GetRsaKey("Key.RSA.Encrypted.Aes.128.CBC.12345.txt", "12345");

            RSAParameters p = rsaKey.GetRSAParameters();

            AssertEqual(p.Modulus, "A16BFBCAA93DCD7F4EE5D1BFFB03906D49D4F2F969C2B7DCFC41532AF394638187389F7702874B449B213712347D06673D6C1211DB05941E72DCDA09835DEE18D5818A4325823D35673CFA4137E79A99AF8160F6DF4039FCC1136C12086D7364E05C7D8E8F6F321A719FEC9338EAB482B32270C7D76812FAC5A6D4068807570A4E9A2E74731610B8ADE55EF62062D72D40E13E665649638F075546920C658B211C48BC99CFE6BD5F9FEEDF5A5C6DF7599FABEAB1944F872CEA1A5CC7283C012B67969C18B8B029797E88FF5AEA18B92D2423C615E140252F8ECBF235B0AEC882F2AA48C4A290A453E612A806B6B810746CA5EE208AA45015FE34DA37EBE042AB");
            AssertEqual(p.Exponent, "010001");
            AssertEqual(p.D, "40AAF0F974A9B4BCCECFD522D31DCF6B690BADB76BBE3D4883AA6BF62615097427C6F0638E18C3779DAA45D4BE40642352010C9028AD68747651B1EBE3BBEA99FA56E61C1657C1CBB62B409A8619FBDE9BE7F9FF8CDABF2059FD3CEB5083009AA623878D683B04D88132AF651F852F81B8E0104C8F283B8A494A97607278764EA0C184A64CBC481AEDE5148ECFE2EBCD7CC4A7D3E6013AD54D4DFC0E9A61F2993A25CAE94B9A8FAC9C8761D2C9E4A2A711EFBEF93FCACDCE777504A270C0DC465688A1851282100D20EB38DD9D24377CE45EE213613DBF7C0EEA9FA10442B1E12165B8EE049FD084EFFC362F6EA5159665FFC0F9D2729BB0A4A84DB9C6F05C79");
            AssertEqual(p.P, "D3B430EFF50E0DF3B5CE1E61B315AD79E8F127D1D09C8983E4C6CBC129653FD4586C7C8A21EFCCFA6166AE753A6D9D4EE6945872A26EEA4796C41F6099B29A3A39484B9073DAD966D9C12E8D59BACF104407F56FC46DA4FB69A98B5BDAA10167C97301E90ECB50A9AE47AA9C48769D50006605F9EB582D5BC01CCAA48F2FA28D");
            AssertEqual(p.Q, "C33275AF4D9842F97C44D261636D3EC1F935C9F484887BDE250CC656796FC5A5D1AFB811E0CE23E066B1C8861664E4D0703A6BA7421AABE1354F6EDECBE4D29FFD79C0AD0C2E6FD6922C50FEA5E34E26F078E3A16DE30A54DD28BBF9FC156BB9D41D62CE25361499D786493AC31486DF64A709D2D4F5C89ED717088674A54817");
            AssertEqual(p.DP, "86C8B9437CF496C36C23AFCA2A178A1C0CC7C4BF5B9EDE1A8004656334B4C6BFAE105BF6220727ACDD685F78395BE284825F3E34B5E001FED4294784DC360EE534E5275EEFB40D27E3499016E4630043EDDC5751F2709052950221BCB8643B9DD56F086F5640F1B92641708911C59B007D50774B979FCB391805FCAA6A933C5D");
            AssertEqual(p.DQ, "00893EF180510EBE08AD57B694C3540CCC566D7B92719D857AAC924EE27E8018787EF70E75839B6D9E5A96A667A1574F8B3F5DD453C626FAB35EC87B2C2C30B7E7C651D527D768CF3A0F8D1965F33DDFB5815F7EAE0295A0AE0AD299592BE5E3D8C54BE42D0DFCF87F330B387218B8561CBCA8B63F877D499265A9CC54BDAF79");
            AssertEqual(p.InverseQ, "3A5615D08581D13AB9C690B8E4A3E0F6D5093DA14C7BA1B80ACFD0D7D292571F79E19079D25F56EA556DA1F64B657FDEA3A070B3BCA446534B311E5FF41B709CEA8CCCF4CA3D0A42CB060F191B9A5625B64D9910CD8344CD014382BFE92CC97C8CD297FA18A01F314F42D8E7CAAD044BAB4D913CD669A688757F830EB0F9F416");
        }

        [TestMethod]
        public void Key_RSA_Encrypted_Aes_192_CBC_12345()
        {
            RsaKey rsaKey = GetRsaKey("Key.RSA.Encrypted.Aes.192.CBC.12345.txt", "12345");

            RSAParameters p = rsaKey.GetRSAParameters();

            AssertEqual(p.Modulus, "B89C9B25E22E35D00C85A4B6E1EC0592ABE5FEABA95B452516F17AA149BE9BD800A543BA419303E6DBF54BD49937F9DD62B730A11C04204168EDD04F6E87F04BFD1CF47C75EACEB6CE9F562EC2AD0DF5932C22CB3CB9EEAAD93C62F2D9F6A81221841DFB31970E6581F6569E3E90B7F94A6A8EAFFD3F232CF81FBECD9C9CFD1FC5563679880BF9559859E976BCC2927E51CCAAE57D9125AD03DF61733033A8AF2A80778F94B9113867D110322E9189B03DA707EFF46CB6CFCAF21AF84133CDFB0806F3BD43D50B58F1011897522ECCFEF8DBCD19ACB8D2E553ECF0EC501E7D9FFBEC4F5FE067E91B97A82778CFAA9E14F1654173C6D0EA257C7D757C32999AB3");
            AssertEqual(p.Exponent, "010001");
            AssertEqual(p.D, "00F3053537A9872B4FB52C38A886BF2C96E7B2DC8D1D6408A1CA9217DC3A37B0EFA7E9E63E4A143E0EA97F3F539E5F118D5D65C99E4C432232F8EE164A7A36791D8F158EC24877D1A6D458EC1AA22B2D35198800458AAB3883AF74CECCE220D11F0CFFDE77CDD00C2393F1B4149C47E5E7450F00C6AB9971B4C0ED093FA1EB07498F11D394D1F5523BC822BB1B5E9BE57F52C9E02A1F36C0FDC56CD5CAC54A868ACB4E6A83251D8A1AFEFB0C722CFF4B474866D8A2D042505E75C723A54A549FBFF37D87786F29184E0042402A20F07D13DDAFE40D7A32C5C60E48D4FA542662FEF1C8F8DEEAA35F00AC11AAB20DE25BE2632D2FB65FA8466E2896B4FD32B831");
            AssertEqual(p.P, "DC82FD955920B802CCE555F8C464F5E6C1C14864F8348AF23E87DB908DB99F4F43458ED5BCD8BCC6A79288E1A35E40530EB7E15AFAA6C88A96B9CF09290BD4876500889A1CE4350C8ADE720DD827A44FC2FED83B8B6B65B108723AFFAEEA31C016DBDE438D124A3C3741E53AF90B248E78CCCDBB76233A98343FF549BD30ECB9");
            AssertEqual(p.Q, "D6528CB7A1F994BD110FE9E83E77FF43D5B6E9C117AF7FFC7605C7CF2EF2985077AD74A3632C88B1277D8B8C629A3DC2899322C14B2282AEF7563A23F16EAFB4877ED646E217EFC5DE7D9DDBFD5E0C908E291B0C304DFF13C2B30272F6F26C6DB255A1FD43C14581E852402438EFAEE04D3FE5C03EED00C468217EFFA27304CB");
            AssertEqual(p.DP, "B0FF03846931F601696D7B805E439B8D496057379472B8449124837C9805B275F0CD5844FF7C08AA7BBF06D7F645A4E406205A66A8624EFDCED5FDF4A059BA91A2E4B6C0DD07DFFCDD4A87C9CD02A4C4D103B594B5E7D28C32F75D9BF54E4DF89D60861B3A94BFB96DB11ACA2734667765471EABA5BBC9407A500C16D0210121");
            AssertEqual(p.DQ, "BA0D1753222D434D8DCE3EC3F9D6B9A5ED94C7FF73CC4A52A332096E75D6EB1A8F89E8431E08BEF0EAD3359D3CCBA0E98BFC4AA379D20F984BE672BA5910393F82903CFB73B24BD77D7996DC2E6AC2858AA36C737C4B792F72496BCAD94D418B48D0C5BAD262A93048B97E2CF3B03E23416C42CA4CD5F96086F4ED0685C34B59");
            AssertEqual(p.InverseQ, "404C8D45530D9EF5DC59BE86AB0B7BC95CCE1A542A8EE914D503A1F9A1B6BE667B1B151FACC6195138DE55377E808A9DD29A513A258C94AC5849BEB27BEB1546C1D7287ED9ED2BF85DB73F422D4BAAAD18B277EED9BC1127E1B14686A3B22812DC35A2EDE4D5B0D33F0AB72C847B83CB061AC580AF6BFD76EC4C45CD45C25F0A");
        }

        [TestMethod]
        public void Key_RSA_Encrypted_Aes_256_CBC_12345()
        {
            RsaKey rsaKey = GetRsaKey("Key.RSA.Encrypted.Aes.256.CBC.12345.txt", "12345");

            RSAParameters p = rsaKey.GetRSAParameters();

            AssertEqual(p.Modulus, "BA2A9270457E077E81629AB453C6A1ECC80A0F80C0FE766DBFE8D8C8662CB608FB8D19F722F842A34A67501E1A8CF2396104A8528809EC12E5B8E961A50B3A509B6B920358450B3FE9744C4DC3DA277D8DA1749C0EAC59433BDACE71E75E661490E600D6FDCFCCADE4100E01124FCB4104CF18BAE93D87AEFADFE09B77B4C0BCEB247E6C7D45744C7856AA60E7BCB95BCD4030182A571F86344449F903B54BC9494CA365890A474C279BD7C518BE8AFE342B6C3606EF9C04C81EBE6D23C797764B6A48C726234E5D594E809564F46C35E3B84B3DDFB3C7213878957927BAD0BFDE90516A2E60F15C303E047E08A77E421B360D36039A279234D355406720ADF5");
            AssertEqual(p.Exponent, "010001");
            AssertEqual(p.D, "32D25A65C1E2D4E2E92964F863826F43F79C1F7D53B263DC342EB9B783852330B293638A3F06AD126CC6656DC26BC5D87A2ECE50B1889BE4D0C7B91689FAD5B199AC35112AB0B6907D07DDA8C115B6002580F517813DF5A4501BBC8E05CE94697AE0FF4BB1C05FACFCFC910623DC9AAD2645EF075F93078E723859D5B74925F0358FA101F0F4351FBE6B42DCC61320A45C56A65D792AE3D3DDBE219E63DA02BBF84967AA057C497C963C358AA7CE69C6BA38C7FF87516431EF14FB29B16717FE36ADC5D405B7305C3B12B0F09A7A22448613C66003F948F2A7FD46A2205D23B519C3C6ED22B9069D0E3890038E4A1EFB4CBC559F1DE9DE905B985B04060DF001");
            AssertEqual(p.P, "E76717EE79AF3F476451F5D189C4AF1F6FAA69C3BEADD3AF167A49D9967EF54CCDB6BE4AC7AEEDC19BA35C717769416FE02B44831B8094C95CC97874EF3FF9ED12D1F5F389CF7065FA73482C4002C72654B4567BACED4E7C773913CF10A44DC0076FB630BCA04DC71B9088C56884D97AEBE07E0613ABBF7FE9060C7C207DB9F5");
            AssertEqual(p.Q, "CDF4828EDED33BBB3C957E2494B3A5CB7BB0D6484B16D1008BF3FDE96765A9C74A0AF887A4C7113D8304258C043884A64BA6B8B3582AFF1D443A697D240C8A03AAB1B341CBA4DE5512B84E788537BF61333BED08E864BA7E6C1C7BD968DFA6865D96EE49E3E806C8DA463A24569EF83502702EDA7DC67A5ADE508436F23AA401");
            AssertEqual(p.DP, "E312E88A0D00EAB0AD023C9E057A6B7B06C20C8D9874CD7058376276D1D6FDF203405B95D843916E56C344F8D77C0349BC89D8EE6B338F4DD5EEA274E53E3B8BE7D6FF6AA0065EBEC3B912CED175A865B5E34DA6897849779C2AF7844F495C3E9F4D81546C15469DA72FFAF6F4ECC0D97DD44AF6BDA0E107ACEC519E10E82F6D");
            AssertEqual(p.DQ, "5BEFA5042FD5AD59448F1B132B4A125D86268751182BE43A513F267E3548BD8417BA53FD010257E0D4865A58695DED60EA6E4F0EC7F1D195F7E9F743047F907058972084E36A0251899CBA72B44D11624B6399C91B2C33CFD164D9A850575DD7A71983DF7A1C0E4344A48AB9C3ED0CB165183CE20DB936CF2F6453D0CF4A7C01");
            AssertEqual(p.InverseQ, "A12255F23426886D6622F0DBC23D8005F13C6ECB1670D736A136C335F0641909287DC2BD9CAC0DA8B5658EAAFFD5B49E35F409A7A1AEC2AC6B0F1C360CA50CB045F127C6C7CF3AAAA40E2EA68301EA459B3BA9F76D4A1BA315834AFF0C0FCB178F28F0569AC34011CC5971E8C159EACE4F8437C26E2B0087A705C438966DC82D");
        }

        [TestMethod]
        public void Key_RSA_Encrypted_Des_Ede3_CBC_12345()
        {
            RsaKey rsaKey = GetRsaKey("Key.RSA.Encrypted.Des.Ede3.CBC.12345.txt", "12345");

            RSAParameters p = rsaKey.GetRSAParameters();

            AssertEqual(p.Modulus, "98DDECDA2329F076AC0D05A8149015615C44D1D7AF8A146072F5B29CA1C80099FBC94751D9735C62C983C5321DF66CDF1934CEA7F4F568056C2D484994C946D42DADBF10E8CE47E560F4ACC50B64B0D72BEEE43C916678055A9657678AD81D55D9085D9C35E436B82E738A581DC664A67431A8907043B95BFCF67D83CEAC329AE08F14E930F855C27726842EBA36B54985D5504A1CF8F922DE54F476AE3DF7159965F8643D70B0411598A652FF4DE1F8C0C60A3510139F43188C19AD6B0890E63DFD0214D34E345D854E5AC1DD5E52F9F1F8EF78EA120F3EFC7556956D313B1D126FD223BBD68EF1C3273FEA3B354A81E344595034FE1BEAAE59F0D62A88BE93");
            AssertEqual(p.Exponent, "010001");
            AssertEqual(p.D, "44E5F174B7D8953AC77CEF09BC8ADC380F802D1C0B502EB2F1DD6F6D4D35799FED6DE0A9315ADF4EDF0876FE89A6A19744231AE9746C8F3FB26C0E62AB9EB43FB97ECFD8ED34DC0EB44E52F85494436817B30A478A3926EB32D303FDF50446E4847752C9AF3876B938A676BA146170C7DD22EC987D20E9105EC931F51057684ED784AA1FE0AB14C47E982B9DEDAFAA3E97A422DDCED05D115673E9DED5AE228A2733F7C4C65528E265523E52C913C9066A19A7376450F820A720F13E7CE36B945748048A471D4D3F5BC3AC249A09A88CC410FA0C32228CCE3468A8A060541A73C17C847904DCC4B2184222990843F55BA9F1B178D0F9676FC30F1048C1D92C31");
            AssertEqual(p.P, "C874E6C096E1F628179CB898799D20F09EFF9CF9C87B6AF28BDB85F8283A8479671498DB7BBC690F24BC946289B694E339129422EFD3DAA21CDC3BBA89F899A08E4CA29E5F16EA601A8AA0E53D496B536A887429A48010E2310FA0AA04F5BD65A9C571B6DF8708E341BDA4FFD3A371C0E80EB792F46BB530C52549CA86FF7717");
            AssertEqual(p.Q, "C3395086C4BCB1BBBA843F2632567FC0B24171152378334B3ED314060F0FD6DD7E95AD2EAC4C3B343E93F721F3B493A150DB5E7CF08FAC1205A3D59070C23CEBB338CEA7BC84A0E0A6DE59EAFE499C7D027E2C9ADCAD9D7EE9F2EF94597A3281D4CA49C63428C091430FC1F54857E2EA2326D57E34BF9A8F98681646D968E1E5");
            AssertEqual(p.DP, "011D051B14BB748E8C730663726979015D20B6527CD692A57E395DE91EF01444485A48EF0F24E0C080C7BB5B40C08EDB243A02309F7C61BE7CC28C6260D9CCA0A3A9B14D87E1ACB393F2292A9CC8879C12FF6705C43021E7DFB5E2828F3C7E2CCE60965D19A8BA57E8C990DD0AE3E181DCC81824ECCE9C5705014C039FF45349");
            AssertEqual(p.DQ, "186DEEA6BEADC22BF4BE21CCDCD5B82CDBE1968E079F3E03F77BA070D5A7ACC290D9980F541E41F65AB2576597428C8ACE3C75497B2CEF625DF44F8040ABFDC59CEAC9E9718CC338F988AF85D9864A9FD61505EDE7198EB0D803BF7937ED33AECD7AF6DA67A285DE679EEC2D8E7CF8F745A8D16476A3576B0AAE53C34FE77105");
            AssertEqual(p.InverseQ, "C0C0C959707C6ABABA1B908C104EC037CE2C9187B17A659342A22BB44231A8AA53BD4AAD277349D87557F114197265001A1384F63E4746FE4CA1545A8D3BF803C2B7A6F46122F5659885DA60F1F88D1891DDFAA274B58A8AE08C2F2F52E89F9C6E3F79CBE16DD4DF2F9DC96442FA67758DCEF2A6F84451476F8347B3E67CAD5D");
        }

        [TestMethod]
        public void Key_RSA_Encrypted_Des_Ede3_CFB_1234567890()
        {
            RsaKey rsaKey = GetRsaKey("Key.RSA.Encrypted.Des.Ede3.CFB.1234567890.txt", "1234567890");

            RSAParameters p = rsaKey.GetRSAParameters();

            AssertEqual(p.Modulus, "B3CB66D69596F093904E9BAFB0695FFF1EECBB7F17B8AA3BCCE2E263FEA007E6415ACE940B74E73F55271B5DEAC92F5EB969885AA573FF777A38CFCEF72B23C20CC18D11902327A4C5B5F10DBF88A58AD947C4F94075C58CFA7FC9719C927BAB51817C1B8B9BC6A24050B7B9942CE0FDBE1A37D571BF5B4C4D175A02B2CF95D7");
            AssertEqual(p.Exponent, "23");
            AssertEqual(p.D, "7103827840C546C32781DE33EB3AEBE230B20F74754F80F263874C795E38B4821A7397CAC55F6CC8B92E863B089BB7601CC5FDEFD5B6A0943E3256BC9B5CF1E6A1D0842ABE79CAA6044D1B1276D75116E57CE6C19DD690EDFB988384023734D27F4D795CE6472793A855A53C5A69C1CA3D8AA21EB113D8833F1F6B93B419F94B");
            AssertEqual(p.P, "E6DADD79CFEE89E89EA263F95B6D475BB472E631720F7EC4B49956A4BBC00F62C852AB1C3F10ADAB80F71EA247D01B1F06524798C8FAB07033302D60AF4F01A7");
            AssertEqual(p.Q, "C760C60DEE444FB408F5F948787F00165AA56FAB0D79A607D88B15EF3A63526E0479615FDE312B7490A2CC65D3CBCBBFE182A88031F68C96EFA98D1FC2117051");
            AssertEqual(p.DP, "3B5CD9DD7E9C6C9AE6F68EBC7698716F5A496E647C6A626D187F3389721B71ABAFDABE491787F224C9641DD1F53583511EE1F527499F8C749F72C9D7088207BD");
            AssertEqual(p.DQ, "60D73BA05DC9688AA54445E15F191D4CAFAF70C0CC07E2EDDE34ED659163712E1F6E27FB5D4B151B5C31D0FE424D0B315046C6DF2E35EC83D37E3D3B4FA211FB");
            AssertEqual(p.InverseQ, "C2A3CAFBAA7370C2692C83B953AB0705B1BB497513BD6798893D41579318D11D6ACE21F8321C229E9DF5A25A404262C9C60D4BD314435C103A9B18E4AD7F07C4");
        }

        [TestMethod]
        public void Key_RSA()
        {
            RsaKey rsaKey = GetRsaKey("Key.RSA.txt");

            RSAParameters p = rsaKey.GetRSAParameters();

            AssertEqual(p.Modulus, "B93B579FE05AB57D6826EBE1A9F259C398DCFE9708C4950F9AEA05087DFE6D77CA049FFDE22C4D113CD905AB32BD3FE8CDBA006C21B7A9C24E6317F60447930085DED632C0A1377518A0B032F64ECA39EC3CDF79FE50A1C1F76705B333A5961319FA14CA55E67BF9B38E32EEFC9D2A5E047997293D1C54FEC79604B5197C5521E20E42CA4D9DFB77086CAA072CF8F91FBD83142BE0BC7AF9DF134B605A029993411AB65F3B9CB5B25570782F38520ED18A2C23C03A0AD7EDF61FA650F027658AD4DEA71B4167C56D478437922BB7B64DB01ADAF65082F1573169CEE0EFCD64AA7808EA4E45ECA589685DB4A023AFFF9C0F8C837CF8E18E328E61FC5BBDD446E1");
            AssertEqual(p.Exponent, "23");
            AssertEqual(p.D, "2A56B4F157DA381CAA17865F774D565897F7FFAD7E58D19D2AB925B8CC57697A775183A7BEAB0A4D1538EB5A54BD8AF3623924AB00647E92D016A6641E3C3EDB8C5030F5A85F5D221441FC636B7FB931CF98E29F8A961658388C9396ACB8224D8247CA3CE06F3247B4033ED78A328D57517AE0B8F80679D3D5D925A5BCAEB45F2017AAC7B00E18BB49E22666898ACDB877DD25E35716A4CC77DAF0111478821E47DA0595032E61DA381AB1E114ED93FA0FE0AB0FE455DD7391E130B74E9F6550C4AD5C29FADC1EC31C6FC2B93808A502CDABDF8437E2E6C27961DCE10C1460932060248F9FD7974ACAAA8E880A5AAD5F7EBB3AC3EAF22E367955A2A4008AE80B");
            AssertEqual(p.P, "F0658B2DF67BCDE7B210649C19F91CE2B6ACEDDAD731F1BD8AFF3732135ED7593A36AD3727D7B64C222E5FDE979B59849BCA7BD9C8B5223FE30EE6BE5BD765F5BC877311D2A6FC6ADE2359AF326B687011EAEA689A27AA38DBF9E061836EE5B59210464F01BFA0295D301691CF9D146844232B28903417ED5EF605DAE2CEEA75");
            AssertEqual(p.Q, "C5412C72B4E4815BF31EDD6A79409835FA6EA08E6C87783DC7B639E38D1488F58C8A30BC25DA134B7DCD4E17E5274DE6E8EABB80EA5E0CD474D78A709C56A453BBE0C0D1C53DC26CCCF7E9F8A4267BF15A5FFEAB41DA958B8263C826D78558713854040AE8DDCF78D4836E7B26C634B200F6373B44C9EC16DC954EF358A5A53D");
            AssertEqual(p.DP, "149AFD4D15208DFDEAB0F2AE4B5E7ED19AA11BB3AC0B9860B4248112EBB7AC0EF65C753F3DEDEB0DD70B4A0BC3DA1D9DA6F4193E8D8BDE5D3F590C76B76A3BF07DDFB967ED7C0701D886AFEA720934D667EF906F5DABA0E04D5E8F9354689758B4BF90FF752DAEA475B3AA29C1569B5964ED1253EF1A68736E8A1DC24DF47A7F");
            AssertEqual(p.DQ, "32B8FCCD09F19D9B4D25319F093C7EE94F06810EAE3176B0CCF458075029DA1341655CFD2E4E04F627A9D240A8A3B4F23BE4969D7E182F2F513EBD32E65F6C15881538E57BDCAE567DD9596BD2704BC1B827501D68B48CDABB20F8F40B88B057A0C5259C67C402266288325A2E8ABD17D45C91DC0A5FCEFE907E2A3E932347BF");
            AssertEqual(p.InverseQ, "ADC31A239335127D5DF30EDE9B6122C1CE05E0A3F66BF654BE8128203FBD83CC83665B681B0347E433666E265B5C7DA90ABF88155FFD73A28CFEEEDFB86E3E9DAADF9B97B858CF45674D20D91AEA392CA0E27FFE20486ADD6E50B640B4EE5F61E358265DB2E7BB991C0BEDC5D1E33948A04F7DF91CA1771BDCE701D27D8AFF24");
        }

        [TestMethod]
        public void Key_SSH2_RSA()
        {
            RsaKey rsaKey = GetRsaKey("Key.SSH2.RSA.txt");

            RSAParameters p = rsaKey.GetRSAParameters();

            AssertEqual(p.Modulus, "D5C19C6D7382399E7802F2A02EEEE26C97DC84A9C700E4C6D41C4C931CBFD290A84CF483017887C8DC63378AA393C9EA83575FB0F7635C24695BE781B10321259D4FA88878581EDF90AEFE5A6E2DC21A9084B43BB8FC239CD7E5358A918B3798279C14A1FB8AD88DF40E088D423C36855E93A2CF2292F540EC609E7639D271161B51AB95F2BAD70BAF979F2EA60F617704613F0907584D95CDB3B98A2240A96FDCE225730CEE3B827C148EA904B0672ED77842AE32ACCFF5D887081CAAA82722A691DCD116532CE3424D66BB9DDA2A01D859A6493FA43AA6153116109B943CDF23582AAE912E11CF15C413795BCD96C89D89AC95D95721E6E842814933EE165F");
            AssertEqual(p.Exponent, "010001");
            AssertEqual(p.D, "9A05EB68767DD474DA770D4ADCE6A6E2A6BE701D41D6E4025CDE9352C1B97AC95F6C2C17A5DCAAC2D202F00786FCBBD6AE932BD18140E829187DEF9FE4E3A363CE2992FFDAEF6C379DB26A76D0C34A05083387072DB1091C3FF8DA0EA1F715B51E7D79E48A332EFD826906427B02962A9DCE75D7194B994B11C84106617DC09B62E1870A303A07C76C15E573AF3C23BB596BDDE12DB82842A609D61DEBDBC9AB0E6164E3DFF32DFD6C745C4010401F63BAD2F8569CCDCEC1350F8EDD2DF55601F958A6909CC451FC2D2ED2AB9344505B345637B52C92BA5E1ADF89E1FC62341FA6C8A46E971321E6C81CFEF85B746306170AB7B781A0785C4A3F2F539A4F8F71");
            AssertEqual(p.P, "F416D8B6B9494FA220E684E219505EEAB37A71902F8E8D97160608BB22C123881C59566607DE20FBDB68266C0E289BABA5031B3B176AB5D25D185D8D5DB36E7414EC50B304F6BDAAF5F00D0C8CE59AED18070A106A887C62FA4ACB5BA17D52F96559899BE1BCF81354F7ADF138381D21E545B6A070F81E7B263C0FEDF4C99699");
            AssertEqual(p.Q, "E02FD8B0B9ED6EEC3E88ACBDBA3F0B9D6C9499DE53EDDD8919976E4B0C856B194E54D313C7DE8F8540F193910BF9AAB738DC8F7A25CF8FF5DEC0D84C84EA3F80AED4962AAE4EAD5500860D7A3B8F6B736BDEE6FE30E777CE1F43F6D011EF935431204839BC7009C207D9309EBCB9BEBEEF782D9121C9E96EFC4F6429A3E747B7");
            AssertEqual(p.DP, "4B9D20394AA0C9488244A6F99BB9E80D70D8078211196A0759CD38BB300300CCD36B61766E0D83CE41A3BBF351578711DF265D332B07E5976B3B770FA9ED41D437FF14E8C02AE78AA4715EB97A944E3010776DC8B417DFE09184C60676BA6A0FD433AE8B599CBE84CE97838CEC4B85CAD0498E4F996F6391E6C048770093CA51");
            AssertEqual(p.DQ, "44CC6A2351EB9B6EC4820D00EC770C897318E75F63424C0A16E071E8761F3B8EB88B2F7B928AAA60AA5D787BBAC113B2C6B069178322FF7AE4B129AFD1DA51429C6480F0F82D0CE45914CA6E08792AF070DA26E93AF8CDBB63BCE7B152CFC2D6C37CB4AD83369EC7FCC09A3B1C8FA409D4537D285CC629ECF56127CBDF90CA61");
            AssertEqual(p.InverseQ, "BCE1B16B5B42F51361AD815A76B99A2255ED729E85E6AFB9C77C299B5494B99C4641613293FBADBF55D94388B9BB4259D0AA9931C98C3E777A4CDEBBC72C06FFEA7B6822C9791C91B85960E5D2F415C23411E4242946BB4B4220C884C03105D2864B9425F51A5D40ABE1148FBB493CEDB6A70309EACE1154064A54F7BCBE7650");
        }

        [TestMethod]
        public void Key_RSA_1277()
        {
            // 1277 bits, exponent = 3
            // openssl genrsa -traditional -3 1277
            var keyString = """
            -----BEGIN RSA PRIVATE KEY-----
            MIIC5gIBAAKBoBUKXQC9ocP8K/mdXgG33wmzhEkahLWCkheVd8MwIlJ8N4NfEhiQ
            k1H5pygn/Ux6gJMwgCH5TI6rMgtGu4TDUuk+aC16ABb14T1RLOiFRiSxuiLzE/Bx
            MH0VYMx5wxKI3c5ndTzPx2w7xXtZ6LqKhmVPBA6/E3+f6XHF1cTHXrwONUOKR7tx
            RTOpMoR4GfJQKfusk8UmnBu1MPqtKKPmJncCAQMCgaAOBuirKRaCqB1RE5QBJT9b
            zQLbZwMjrGFlDk/XdWw2/XpXlLa7CwzhURoaxVOIUasMywAWpjMJx3ayLyet14yb
            fvAeUVVko+t+Nh3wWNlty2q//LjQMg8XQeDZcGlXJ0KA9JQnLIVHrs/h/qdiSKng
            AECZ+3v6kuaIYTuImV4s1kAvyj1vstJEdE0yAIjIYF/VRF0FMQHu2cN/8kYk/g2r
            AlBkUcwlrkIbiwUokbYH4DnCoWQJdjQm95geEfzCIVhEXJaszFlW++ZwUmxLYE42
            h1FtnesTiX/U8O0WPLS4RD8E8XYiYXH9a9+bMj0qAEYvNwJQNbEr2Qnj/k8tZvSb
            HS+UN2uUjYvY2Ikdb5ZfK4XFQzi39ltsgovdH1LHsReTGvF7Z13v2AplNNwNqHzC
            lIGAlUpP5dvrG8mO8IiElWwi4sECUELhMsPJgWeyA3BhJAVAJoHA7VukIsSlEBQL
            /dbA5YLoZHMy5jn9RErhnYeViXmvi55pR2Jbqo3182QoeHrYKgNLpBbroVOdP7zM
            KMaq2XTPAlAjy3KQsUKpih5EoxITdQ16R7heXTs7BhOfuZTHroOCJc/5kkhXB+i/
            jIUgumIR9lJE6UqQBu4jPV5wUyxjAQBjht/ukpy9MQn1sFhjnWyXKwJQEnbmS2Pl
            GRDqEnMJEBqKjnvFRX/vyoa8ey3UdnTU8u6HYMousA8aYXKy4iz60ju0JFl+E4Fc
            a1wk0j6pQa4XVPZ+ff/6GqC5wX5DEY2dk4c=
            -----END RSA PRIVATE KEY-----
            """;

            using MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(keyString));

            RsaKey rsaKey = (RsaKey)new PrivateKeyFile(stream).Key;

            RSAParameters p = rsaKey.GetRSAParameters();

            AssertEqual(p.Modulus, "150A5D00BDA1C3FC2BF99D5E01B7DF09B384491A84B58292179577C33022527C37835F1218909351F9A72827FD4C7A8093308021F94C8EAB320B46BB84C352E93E682D7A0016F5E13D512CE8854624B1BA22F313F071307D1560CC79C31288DDCE67753CCFC76C3BC57B59E8BA8A86654F040EBF137F9FE971C5D5C4C75EBC0E35438A47BB714533A932847819F25029FBAC93C5269C1BB530FAAD28A3E62677");
            AssertEqual(p.Exponent, "03");
            AssertEqual(p.D, "0E06E8AB291682A81D51139401253F5BCD02DB670323AC61650E4FD7756C36FD7A5794B6BB0B0CE1511A1AC5538851AB0CCB0016A63309C776B22F27ADD78C9B7EF01E515564A3EB7E361DF058D96DCB6ABFFCB8D0320F1741E0D9706957274280F494272C8547AECFE1FEA76248A9E0004099FB7BFA92E688613B88995E2CD6402FCA3D6FB2D244744D320088C8605FD5445D053101EED9C37FF24624FE0DAB");
            AssertEqual(p.P, "6451CC25AE421B8B052891B607E039C2A16409763426F7981E11FCC22158445C96ACCC5956FBE670526C4B604E3687516D9DEB13897FD4F0ED163CB4B8443F04F176226171FD6BDF9B323D2A00462F37");
            AssertEqual(p.Q, "35B12BD909E3FE4F2D66F49B1D2F94376B948D8BD8D8891D6F965F2B85C54338B7F65B6C828BDD1F52C7B117931AF17B675DEFD80A6534DC0DA87CC2948180954A4FE5DBEB1BC98EF08884956C22E2C1");
            AssertEqual(p.DP, "42E132C3C98167B20370612405402681C0ED5BA422C4A510140BFDD6C0E582E8647332E639FD444AE19D87958979AF8B9E6947625BAA8DF5F36428787AD82A034BA416EBA1539D3FBCCC28C6AAD974CF");
            AssertEqual(p.DQ, "23CB7290B142A98A1E44A31213750D7A47B85E5D3B3B06139FB994C7AE838225CFF992485707E8BF8C8520BA6211F65244E94A9006EE233D5E70532C6301006386DFEE929CBD3109F5B058639D6C972B");
            AssertEqual(p.InverseQ, "1276E64B63E51910EA127309101A8A8E7BC5457FEFCA86BC7B2DD47674D4F2EE8760CA2EB00F1A6172B2E22CFAD23BB424597E13815C6B5C24D23EA941AE1754F67E7DFFFA1AA0B9C17E43118D9D9387");
        }
    }
}
